package com.blue.integration.serve.ucpaas;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.blue.core.auth.DigestUtil;
import com.blue.core.http.HttpInvoker;
import com.blue.core.util.UrlUtil;
import com.blue.integration.serve.SmsClient;
import com.blue.integration.serve.SmsClientException;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.Header;
import org.apache.http.message.BasicHeader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;

import java.text.MessageFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;

/**
 * @author zhengjin
 * @since 1.0 2017年12月05日
 */
public class UcpaasSmsClient implements SmsClient, InitializingBean
{
	private static Logger logger = LoggerFactory.getLogger(UcpaasSmsClient.class);

	private static DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
	public static final String FUNCTION = "Messages";
	public static final String OPERATION = "templateSMS";

	private String host;
	private String url;
	private String accountId;
	private String token;
	private String appId;
	private String smsId;

	private HttpInvoker httpInvoker;

	public UcpaasSmsClient()
	{
	}

	@Override
	public String sendValid(String mobile, String num)
	{
		return this.send(mobile, smsId, num);
	}

	/**
	 * 发送短信
	 *
	 * @param mobile 手机号码
	 * @param templateId 短信模板ID
	 * @param params 短信参数
	 * @return 发送短信序列号
	 */
	public String send(String mobile, String templateId, String...params)
	{
		SmsRequest request = new SmsRequest();
		request.setAppId(appId);
		request.setParam(StringUtils.join(params, ","));
		request.setTemplateId(templateId);
		request.setTo(mobile);
		Map<String, Object> map = new HashMap<>();
		map.put(OPERATION, request);

		String json = JSON.toJSONString(map);
		Auth auth = this.getAuth(accountId, token, null);
		String u = url + auth.sign;
		logger.info("发送短信URL={}, json={}", u, json);

		Header hostHeader = new BasicHeader("Host", host);
		Header acceptHeader = new BasicHeader("Accept", "application/json");
		Header contentTypeHeader = new BasicHeader("Content-Type", "application/json;charset=utf-8");
		Header authorizationHeader = new BasicHeader("Authorization", auth.authorization);
		String resp = null;
		try
		{
			resp = httpInvoker.post(u, json, hostHeader, acceptHeader, contentTypeHeader, authorizationHeader);
			logger.info("发送短信结果：{}", resp);
		}
		catch (Exception e)
		{
			logger.error("发送短信出错误：", e);
			throw new SmsClientException(SmsClientException.ERROR);
		}
		JSONObject jsonObject = JSON.parseObject(resp);
		SmsResponse response = jsonObject.getObject("resp", SmsResponse.class);
		if (response == null || response.getTemplateSMS() == null)
			return null;

		TemplateSMS templateSMS = response.getTemplateSMS();
		return templateSMS.getSmsId();
	}


	@Override
	public void afterPropertiesSet() throws Exception
	{
		if (url == null || url.isEmpty())
			throw new SmsClientException(SmsClientException.CONFIG + "url");
		if (accountId == null || accountId.isEmpty())
			throw new SmsClientException(SmsClientException.CONFIG + "accountId");
		if (token == null || token.isEmpty())
			throw new SmsClientException(SmsClientException.CONFIG + "token");
		if (appId == null || appId.isEmpty())
			throw new SmsClientException(SmsClientException.CONFIG + "appId");
		if (smsId == null || smsId.isEmpty())
			throw new SmsClientException(SmsClientException.CONFIG + "smsId");

		this.host = UrlUtil.getHost(url);
		url = MessageFormat.format(url, accountId, FUNCTION, OPERATION);
		logger.info("初始化 云之讯 短信接口：{}", url);
	}


	/**
	 * 云之讯认证对象
	 *
	 * @author zhengj
	 * @since 1.0 2016年12月1日
	 */
	public static class Auth
	{
		/**
		 * 验证
		 */
		public String sign;
		/**
		 * 包头验证
		 */
		public String authorization;
	}

	/**
	 * 返回云之讯时间戳格式
	 *
	 * @param time 时间，null为当前时间
	 * @return 云之讯时间戳格式
	 */
	public String getTimestamp(LocalDateTime time)
	{
		if (time == null)
			time = LocalDateTime.now();

		return time.format(formatter);
	}

	/**
	 * 云之讯认证方法
	 *
	 * @param sid 账户Id
	 * @param token 账户授权令牌
	 * @param time 时间
	 * @return 云之讯认证对象
	 */
	public Auth getAuth(String sid, String token, LocalDateTime time)
	{
		Assert.hasText(sid, "账户Id不能为空");
		Assert.hasText(token, "账户授权令牌");
		String timestamp = this.getTimestamp(time);
		String src = sid + ":" + timestamp;
		Auth auth = new Auth();
		auth.sign = DigestUtil.md5Hex(sid + token + timestamp).toUpperCase();
		auth.authorization = Base64.getEncoder().encodeToString(src.getBytes());
		logger.debug("云之讯：sig={}, authorization={}", auth.sign, auth.authorization);
		return auth;
	}

	public void setUrl(String url)
	{
		this.url = url;
	}

	public void setAccountId(String accountId)
	{
		this.accountId = accountId;
	}

	public void setToken(String token)
	{
		this.token = token;
	}

	public void setAppId(String appId)
	{
		this.appId = appId;
	}

	public void setSmsId(String smsId)
	{
		this.smsId = smsId;
	}

	public void setHttpInvoker(HttpInvoker httpInvoker)
	{
		this.httpInvoker = httpInvoker;
	}
}
